package com.rj.util;

import cn.hutool.core.text.StrFormatter;
import com.rj.core.check.AssertorBean;
import com.rj.core.check.Dict;
import com.rj.core.check.DictList;
import com.rj.core.constant.CompareType;
import com.rj.core.constant.DigitsEnum;
import com.rj.core.exception.AssertException;

import java.util.Arrays;
import java.util.Collection;

public class AssertUtils {


    /**
     * 消息处理
     *
     * @param message
     */
    public static void handlerMessage(String message, Object... params) {
        String msg = StrFormatter.format(message, params);
        throw new AssertException(msg);
    }

    /**
     * 参数异常处理
     *
     * @param message
     * @param params
     */
    public static void illegalArgumentException(String message, Object... params) {
        String msg = StrFormatter.format(message, params);
        throw new IllegalArgumentException(msg);
    }

    /**
     * 为true抛出异常或错误
     *
     * @param expression
     * @param message
     * @param msgArgs
     * @throws RuntimeException
     */
    public static void isTrue(boolean expression, String message, Object... msgArgs) throws RuntimeException {
        if (expression) {
            handlerMessage(message, msgArgs);
        }
    }

    /**
     * 为false抛出异常或错误
     *
     * @param expression
     * @param message
     * @param msgArgs
     * @throws RuntimeException
     */
    public static void isFalse(boolean expression, String message, Object... msgArgs) throws RuntimeException {
        isTrue(!expression, message, msgArgs);
    }

    /**
     * 不是集合类型报错
     *
     * @param title
     * @param value
     * @param <V>
     */
    public static <V> void notCollection(String title, V value) throws RuntimeException {
        if (value instanceof Collection coll && coll.isEmpty()) {
            handlerMessage("{}不能为空", title);
        }
    }

    /**
     * ]
     * 等于比较
     *
     * @param value
     * @param target
     * @param title
     * @param <V>
     * @throws RuntimeException
     */
    public static <V> void eq(boolean allowNull, V value, V target, String title) throws RuntimeException {
        if (!VerifyUtils.compare(allowNull, value, target, CompareType.EQ)) {
            handlerMessage("{}的值{}不相等于{}", title, value, target);
        }
    }

    /**
     * 比较数值大小
     *
     * @param title
     * @param value
     * @param target
     * @param type
     * @param <V>
     */
    public static <V> void compare(boolean allowNull, String title, V value, V target, CompareType type) throws RuntimeException {
        if (!VerifyUtils.compare(allowNull, value, target, type)) {
            handlerMessage("{}的值{},必须{}{}", title, value, type.getDesc(), target);
        }
    }

    /**
     * 数值在范围内
     *
     * @param minVal
     * @param maxVal
     * @return
     */
    public static <V> void between(boolean allowNull, String title, V value, V minVal, V maxVal) throws RuntimeException {
        between(allowNull, title, value, minVal, maxVal, CompareType.LE, CompareType.GE);
    }

    /**
     * 数值在范围内
     *
     * @param minVal
     * @param maxVal
     * @return
     */
    public static <V> void between(boolean allowNull, String title, V value, V minVal, V maxVal, CompareType minType, CompareType maxType) throws RuntimeException {
        boolean allNull = minVal == null && maxVal == null;
        if (!allNull && VerifyUtils.between(allowNull, value, minVal, minType, maxVal, maxType) == false) {
            handlerMessage("{}的值,必须{}{}~{}{}", title, minType.getDesc(), minVal, maxType.getDesc(), maxVal);
        }
    }


    /**
     * 最大长度
     *
     * @param maxLength
     * @return
     */
    public static <V> void maxLen(boolean allowNull, String title, String value, Integer maxLength) throws RuntimeException {
        length(allowNull, title, value, null, maxLength);
    }

    /**
     * 最小长度
     *
     * @param minLength
     * @return
     */
    public static <V> void minLen(boolean allowNull, String title, String value, Integer minLength) throws RuntimeException {
        length(allowNull, title, value, minLength, null);
    }

    /**
     * @param targetLength
     * @return
     */
    public static void length(boolean allowNull, String title, String value, Integer targetLength) throws RuntimeException {
        isTrue(VerifyUtils.len(allowNull, value, targetLength), "{}长度必须为{}", title, targetLength);
    }

    /**
     * @param targetLength
     * @return
     */
    public static <V> void length(boolean allowNull, String title, V[] value, Integer targetLength) throws RuntimeException {
        isTrue(VerifyUtils.len(allowNull, value, targetLength), "{}长度必须为{}", title, targetLength);
    }

    /**
     * 字符长度在最大最小范围内
     *
     * @param minLength
     * @param maxLength
     * @return
     */
    public static void length(boolean allowNull, String title, String value, Integer minLength, Integer maxLength) throws RuntimeException {
        if (minLength == null && maxLength == null) {
            return;
        }
        int length = value.length();
        Integer min = minLength == null ? 0 : minLength;
        Integer max = maxLength == null ? Integer.MAX_VALUE : maxLength;
        if (VerifyUtils.between(allowNull, length, min, max)) {
            return;
        }
        handlerMessage("{}数据长度不允许范围,输入长度:{},允许长度范围:{}-{}", title, length, min, max);

    }

    /**
     * 在选择范围
     *
     * @param values
     * @return
     */
    public static <V> void in(boolean allowNull, String title, V value, V... values) throws RuntimeException {
        if (VerifyUtils.in(allowNull, value, values) == false) {
            handlerMessage("{}值不匹配,输入:{},可选:{}", title, value, Arrays.toString(values));
        }

    }

    /**
     * 在选择范围
     *
     * @param values
     * @return
     */
    public static <V> void in(boolean allowNull, String title, V value, DictList<V> values) throws RuntimeException {
        in(allowNull, title, value, values, null);
    }

    /**
     * 在选择范围
     *
     * @param values
     * @return
     */
    public static <V, T> void in(boolean allowNull, String title, V value, DictList<V> values, AssertorBean<T> bean) throws RuntimeException {
        VerifyUtils.notNull(allowNull, value, (e) -> {
            for (Dict<V> dic : values.getDicts()) {
                if (value.equals(dic.getVal())) {
                    values.setChoice(dic);
                    if (bean != null) {
                        dic.trigger(bean);
                    }
                    return true;
                }
            }
            handlerMessage("{}值不匹配,输入:{},可选:{}", title, value, Arrays.toString(values.getDicts()));
            return false;
        });
    }

    /**
     * 必须为空
     *
     * @return
     */
    public static <V> void mustNull(String title, V value) throws RuntimeException {
        if (VerifyUtils.notNull(value)) {
            handlerMessage("{}必须为空", title);
        }
    }

    /**
     * 必须为空
     *
     * @return
     */
    public static void mustEmpty(String title, String value) throws RuntimeException {
        if (VerifyUtils.notEmpty(value)) {
            handlerMessage("%必须为空", title);
        }
    }

    /**
     * 不为空且长度小于等于maxLength
     *
     * @return
     */
    public static void notEmpty(String title, String value, int maxLength) throws RuntimeException {
        maxLen(false, title, value, maxLength);
    }

    /**
     * 不为空且长度等于length
     *
     * @return
     */
    public static void notEmptyAndLength(String title, String value, int length) throws RuntimeException {
        length(false, title, value, length);
    }

    /**
     * 可以为空且长度小于等于maxLength
     *
     * @return
     */
    public static void isEmpty(String title, String value, int maxLength) throws RuntimeException {
        maxLen(true, title, value, maxLength);
    }

    /**
     * 可以为空且长度等于length
     *
     * @return
     */
    public static void isEmptyAndLength(String title, String value, int length) throws RuntimeException {
        length(true, title, value, length);
    }

    /**
     * 不为空
     *
     * @return
     */
    public static void notNull(String title, Object value) throws RuntimeException {
        if (VerifyUtils.notNull(value)) {
            handlerMessage("{}不能为空", title);
        }
    }

    /**
     * 整数最大位数
     *
     * @return
     */
    public static void maxDigits(boolean allowNull, String title, String value, int integer, int fraction, DigitsEnum type) {
        String prefix = type.getFh();
        String numRegexp = "^" + prefix + "(0|([1-9]\\d{0," + (integer - 1) + "}))\\.?\\d{0," + fraction + "}$";
        match(allowNull, title, value, numRegexp, "最大整数位数：{},小数位数：{},必须负数：{}", integer, fraction, DigitsEnum.NEGATIVE.equals(type));
    }

    /**
     * @param integer
     * @param fraction
     * @return
     */
    public static void maxDigits(boolean allowNull, String title, String value, int integer, int fraction) throws RuntimeException {
        maxDigits(allowNull, title, value, integer, fraction, null);
    }

    /**
     * 整数最大位数
     *
     * @return
     */
    public static void match(boolean allowNull, String title, String value, String regex, String message, Object... msgParams) throws RuntimeException {
        if (regex == null) {
            illegalArgumentException("{}校验,AssertUtil.match操作时,正则表达式不能为空。", title);
        }
        if (VerifyUtils.match(allowNull, value, regex) == false) {
            handlerMessage("{}格式不正确.{}", title, StrFormatter.format(message, msgParams));
        }

    }

    /**
     * 整数最大位数
     *
     * @return
     */
    public static void match(boolean allowNull, String title, String value, String regex) throws RuntimeException {
        match(allowNull, title, value, regex, "");
    }

    /**
     * 有效的日期格式
     *
     * @return
     */
    public static void dateFormat(boolean allowNull, String title, String value, String[] formats) throws RuntimeException {
        for (String format : formats) {
            if (VerifyUtils.validDate(allowNull, value, format)) {
                return;
            }
        }
        handlerMessage("{}格式不正确或值无效,允许格式{},请填写有效日期时间值。", title, Arrays.toString(formats));
    }

    /**
     * validation 校验提示
     *
     * @return
     */
    public static void validation(Object bean) throws RuntimeException {
        String validate = ValidationUtils.validate(bean);
        if (VerifyUtils.notEmpty(validate)) {
            handlerMessage(validate);
        }
    }
}
